/* Copyright (C) 2008, 2009, 2010 Faindu GmbH, Switzerland.
* All Rights Reserved. The following is Source Code and is subject to all restrictions 
* on such code as contained in the license accompanying this project. */
package blocstac.editimage.base
{
import blocstac.api.blocbox.ImageLoader;
import blocstac.util.CreateLogger;

import flash.display.Bitmap;
import flash.display.Loader;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.utils.ByteArray;

import mx.logging.ILogger;

/**
 * Load an image as soon as the url is set.
 */
public class ImageLoaderImpl implements ImageLoader
{
	
	function ImageLoaderImpl(loadErrorHandler:Function) {
		_loadErrorHandler = loadErrorHandler
	}	
	
	private static const LOG:ILogger = CreateLogger.withClassNameOf(ImageLoaderImpl)
	
	private var _loadErrorHandler:Function	
	private var _whenCompleted:Vector.<Function> = new Vector.<Function>()
	
	//----------------------------------
	//  image
	//----------------------------------	
	private var _image: Bitmap
	/**
	 * This is the bitmap of the image. Bitmap also allows access
	 * to the original <code>BitmapData</code>.
	 */
	public function get image(): Bitmap {
		return _image
	}

	//----------------------------------
	//  url
	//----------------------------------		
	private var _url: String
	/**
	 * @inheritDoc
	 * 
	 * @example Either http/https:  
	 * <listing version="3.0" >http://www.example.com/myimage.jpg</listing>
	 * @example or the file protocoll can be used:
	 * <listing version="3.0" >file://C:/devl/myimage.png</listing>
	 * 
	 * @see #showBitmap
	 */
	public function get url(): String {
		return _url
	}

	//----------------------------------
	//  bytes
	//----------------------------------		
	private var _bytes:ByteArray
	/** @inheritDoc */
	public function get bytes():ByteArray {
		return _bytes
	}

	public function setBytes(value:ByteArray):void {
		_bytes = value
	}
	
	//-------------------------------------------------------------------------- 
	//
	//  Methods
	//
	//--------------------------------------------------------------------------
	//----------------------------------
	//  fromUrl
	//----------------------------------	
	private var _loader:Loader
	/** @inheritDoc */
	public function fromUrl(url:String): void {
		_url = url
		_loader = new Loader()
		_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadingCompleteHandler)
		_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadErrorHandler)

		var loaderContext:LoaderContext = new LoaderContext()
		loaderContext.checkPolicyFile = true
		_loader.load(new URLRequest(_url), loaderContext)
	}
	
	/**
	 * If the image is bigger than the max, it gets automatically scaled.
	 */
	protected function loadingCompleteHandler(event:Event): void {
		var bitmap:Bitmap = Bitmap(event.currentTarget.content)
		fromBitmap(bitmap)
	}
	
	private function loadErrorHandler(ioErrorEvent:IOErrorEvent): void {
		LOG.warn("Failed loading image", ioErrorEvent)
		if (_loadErrorHandler != null) {
			_loadErrorHandler(ioErrorEvent)
		}
		removeListener()
	}

	//----------------------------------
	//  fromBitmap
	//----------------------------------	
	/** @inheritDoc
	 * @see fromUrl()
	 */
	public function fromBitmap(bitmap:Bitmap, url:String=null): void {
		_url = url
		_image = bitmap
		_image.smoothing = true
		
		for each (var whenCompleted:Function in _whenCompleted) {
			whenCompleted()
		}
		removeListener()
	}

	//----------------------------------
	//  clone
	//----------------------------------	
	/** @inheritDoc */
	public function clone():ImageLoader {
		var clone:ImageLoaderImpl = new ImageLoaderImpl(_loadErrorHandler)
		clone._url = _url
		if (_image) {
			var clonedImage:Bitmap = new Bitmap(_image.bitmapData.clone(), "auto", true)
			clone._image = clonedImage
		}
		return clone
	}
	
	//----------------------------------
	//  hasLoaded
	//----------------------------------	
	public function hasLoaded():Boolean {
		return _image != null
	}
	
	//----------------------------------
	//  whenCompleted
	//----------------------------------	
	public function whenCompleted(whenCompleted:Function): void {
		_whenCompleted.push(whenCompleted)
	}
	
	//----------------------------------
	//  removeListener
	//----------------------------------	
	public function removeListener(): void	{
		_whenCompleted = null
		_loadErrorHandler = null
	}
	
	//----------------------------------
	//  dispose
	//----------------------------------	
	public function dispose():void {
		if (_loader) {
			_loader = null
		}
		if (_image) {
			if (_image.bitmapData) _image.bitmapData.dispose()
			_image = null
		}
		_bytes = null
		removeListener()
	}
	
}
}